#include "graphics.h"

char* Graphics2D::DEFAULT_PS_SHADER = "TextureMap.fx";
char* Graphics2D::DEFAULT_VS_SHADER = "TextureMap.fx";

Graphics2D::Graphics2D()
{

}

void Graphics2D::setClearColor(const float* newColor)
{
	clearColor = newColor;
}

void Graphics2D::Initialize(DirectXInterface* directXInterface)
{
	Graphics2D::directxInterface = directXInterface;

}

void Graphics2D::LoadTexture(const char* filePath, Image* image)
{
	HRESULT d3dResult;
	ID3D11ShaderResourceView* colorMap;

	d3dResult = D3DX11CreateShaderResourceViewFromFile( directxInterface->d3dDevice_,
        filePath, 0, 0, &colorMap, 0 );

    if( FAILED( d3dResult ) )
    {
        DXTRACE_MSG( "Failed to load the texture image!" );
        return;
    }

    D3D11_SAMPLER_DESC colorMapDesc;
    ZeroMemory( &colorMapDesc, sizeof( colorMapDesc ) );
    colorMapDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
    colorMapDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
    colorMapDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
    colorMapDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
    colorMapDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
    colorMapDesc.MaxLOD = D3D11_FLOAT32_MAX;

	ID3D11SamplerState* colorSampler;
	d3dResult = directxInterface->d3dDevice_->CreateSamplerState( &colorMapDesc, &colorSampler );

    if( FAILED( d3dResult ) )
    {
        DXTRACE_MSG( "Failed to create color map sampler state!" );
        return;
    }
	ID3D11VertexShader* vertexShader;
	ID3D11PixelShader* pixelShader;
	ID3D11InputLayout* inputLayout;

	LoadShader(DEFAULT_VS_SHADER, DEFAULT_PS_SHADER, &vertexShader, &pixelShader, &inputLayout);

	image->setColorMap(colorMap, directxInterface->d3dDevice_);
	image->setColorSampler(colorSampler);
	image->setPixelShaderInfo(pixelShader);
	image->setVertexShaderInfo(vertexShader);
	image->setInputLayout(inputLayout);
}


void Graphics2D::LoadTexture(const char* imagePath, const char* vertexShaderPath, const char* pixelShaderPath, Image* image)
{
	LoadTexture(imagePath, image);

	ID3D11VertexShader* vertexShader;
	ID3D11PixelShader* pixelShader;
	ID3D11InputLayout* inputLayout;

	LoadShader(vertexShaderPath, pixelShaderPath, &vertexShader, &pixelShader, &inputLayout);

	image->setPixelShaderInfo(pixelShader);
	image->setVertexShaderInfo(vertexShader);
	image->setInputLayout(inputLayout);

}

void Graphics2D::LoadShader(const char* vertexShaderPath, const char* pixelShaderPath, ID3D11VertexShader** vetexShaderInfo, 
								  ID3D11PixelShader** pixelShaderInfo, ID3D11InputLayout** inputLayout)
{
	ID3DBlob* vsBuffer = 0;

    bool compileResult = directxInterface->CompileD3DShader( "TextureMap.fx", "VS_Main", "vs_4_0", &vsBuffer );

    if( compileResult == false )
    {
        DXTRACE_MSG( "Error compiling the vertex shader!" );
        return;
    }

    HRESULT d3dResult;

	d3dResult =  directxInterface->d3dDevice_->CreateVertexShader( vsBuffer->GetBufferPointer( ),
        vsBuffer->GetBufferSize( ), 0, vetexShaderInfo );

    if( FAILED( d3dResult ) )
    {
        DXTRACE_MSG( "Error creating the vertex shader!" );

        if( vsBuffer )
            vsBuffer->Release( );

        return;
    }

    D3D11_INPUT_ELEMENT_DESC solidColorLayout[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }
    };

    unsigned int totalLayoutElements = ARRAYSIZE( solidColorLayout );

	d3dResult = directxInterface->d3dDevice_->CreateInputLayout( solidColorLayout, totalLayoutElements,
        vsBuffer->GetBufferPointer( ), vsBuffer->GetBufferSize( ), inputLayout );

    vsBuffer->Release( );

    if( FAILED( d3dResult ) )
    {
        DXTRACE_MSG( "Error creating the input layout!" );
        return;
    }

    ID3DBlob* psBuffer = 0;

    compileResult =directxInterface->CompileD3DShader( "TextureMap.fx", "PS_Main", "ps_4_0", &psBuffer );

    if( compileResult == false )
    {
        DXTRACE_MSG( "Error compiling pixel shader!" );
        return;
    }

    d3dResult = directxInterface->d3dDevice_->CreatePixelShader( psBuffer->GetBufferPointer( ),
        psBuffer->GetBufferSize( ), 0, pixelShaderInfo );

    psBuffer->Release( );

    if( FAILED( d3dResult ) )
    {
        DXTRACE_MSG( "Error creating pixel shader!" );
        return;
    }
}

void Graphics2D::Draw(Image* image, XMFLOAT2 pos)
{

	if (directxInterface->d3dContext_ == 0)
		return;

    unsigned int stride = sizeof( DirectXInterface::VertexPos );
    unsigned int offset = 0;

	directxInterface->d3dContext_->IASetInputLayout( image->getInputLayout());
	
	ID3D11Buffer* vertexbuffer = image->getVertexBuffer();
	directxInterface->d3dContext_->IASetVertexBuffers( 0, 1, &vertexbuffer, &stride, &offset );
	directxInterface->d3dContext_->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

	directxInterface->d3dContext_->VSSetShader(image->getVertexShaderInfo(), 0, 0);
	directxInterface->d3dContext_->PSSetShader(image->getPixelShaderInfo(), 0, 0);
	
	ID3D11ShaderResourceView* colorMap = image->getColorMap();
	directxInterface->d3dContext_->PSSetShaderResources(0, 1, &colorMap);

	ID3D11SamplerState* samplerState = image->getColorMapSampler();
	directxInterface->d3dContext_->PSSetSamplers(0, 1, &samplerState);

	XMMATRIX translation = XMMatrixTranslation( pos.x, pos.y, 0 );
    XMMATRIX rotationZ = XMMatrixRotationZ( 0 );
    XMMATRIX scale = XMMatrixScaling( 1.0f, 1.0f, 1.0f );

	XMMATRIX mvp = XMMatrixMultiply( (translation * rotationZ * scale), XMLoadFloat4x4( &directxInterface->viewProjectionMatrix ) );
    mvp = XMMatrixTranspose( mvp );

	directxInterface->d3dContext_->UpdateSubresource( directxInterface->mvpCB_, 0, 0, &mvp, 0, 0 );
    directxInterface->d3dContext_->VSSetConstantBuffers( 0, 1, &directxInterface->mvpCB_ );

	directxInterface->d3dContext_->Draw(6, 0);

	
}

void Graphics2D::Begin()
{
	directxInterface->d3dContext_->ClearRenderTargetView(directxInterface->backBufferTarget_, clearColor);
}

void Graphics2D::End()
{
	directxInterface->swapChain_->Present(0,0);
}